#include "scene.h"

#include "consoleoutput.h"


Scene::Scene( const char* objFile, char* bumpFile, bool linearDeformation ) :
	model( DeformableMesh( linearDeformation? DEFORMATION_MODE_LINEAR : DEFORMATION_MODE_QUADRATIC, -0.5f ) ),
	renderingMode( RENDERING_MODE_TRIANGLES )
{
	// loading model
	model.import( objFile );

	// loading normal map texture
	//GLuint texture;
	//img.Load( bumpFile );

	// generating model info buffer
	//numberOfTriangles = model.getNumberOfIndices() / 3;
	numberOfVertices = model.getNumberOfVertices();
	modelBuffer = (float*) malloc(sizeof(float) * numberOfVertices * 16 );

	//GLuint positionBufferObject;
	glGenBuffers(1, &bufferId);
	generateModelBuffer();
	
	//glGenTextures( 1, &texture );
 //   glBindTexture( GL_TEXTURE_2D, texture );
 //   glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
 //   
 //   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 //   glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//glActiveTexture( GL_TEXTURE0 );

	//// generate the texture
 //   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, img.width, img.height,
 //       0, img.format, GL_UNSIGNED_BYTE, img.data);
}


Scene::~Scene(void)
{
	free( modelBuffer );
}

void Scene::generateModelBuffer()
{
	numberOfVertices = model.getNumberOfVertices();

	for(int i = 0; i < numberOfVertices; i++) 
	{
		const ModelOBJ::Vertex &v = model.getVertexForDrawing( i );
		modelBuffer[ i*4 ] = v.position[0]; 
		modelBuffer[ i*4 + 1] = v.position[1];			
		modelBuffer[ i*4 + 2] = v.position[2];
		modelBuffer[ i*4 + 3] = 1.0f;
	}

	//// generating normals
	//for(int i = 0; i < numberOfTriangles; i++) 
	//{
	//	for( int j = 0; j < 3; j++)
	//	{
	//		const ModelOBJ::Vertex &v = model.getVertexForDrawing(model.getIndexBuffer()[i*3 + j]);
	//		modelBuffer[numberOfTriangles*12 + i*12 + j*4    ] = v.normal[0];
	//		modelBuffer[numberOfTriangles*12 + i*12 + j*4 + 1] = v.normal[1];
	//		modelBuffer[numberOfTriangles*12 + i*12 + j*4 + 2] = v.normal[2];
	//		modelBuffer[numberOfTriangles*12 + i*12 + j*4 + 3] = 1.0f;
	//	}
	//}

	//// texture coordinates
	//for(int i = 0; i < numberOfTriangles; i++) 
	//{
	//	for( int j = 0; j < 3; j++)
	//	{
	//		ModelOBJ::Vertex v = model.getVertexForDrawing(model.getIndexBuffer()[i*3 + j]);
	//		  
	//		modelBuffer[numberOfTriangles*24 + i*6 + j*2    ] = v.texCoord[0];
	//		modelBuffer[numberOfTriangles*24 + i*6 + j*2 + 1] = v.texCoord[1];
	//	}
	//}

	//// tangent vectors
	//for(int i = 0; i < numberOfTriangles; i++) 
	//{
	//	long i1 = model.getIndexBuffer()[i*3];
 //       long i2 = model.getIndexBuffer()[i*3 + 1];
 //       long i3 = model.getIndexBuffer()[i*3 + 2];
 //       
	//	const float* v1 = model.getVertex(i1).position;
 //       const float* v2 = model.getVertex(i2).position;
 //       const float* v3 = model.getVertex(i3).position;
 //       
	//	const float* w1 = model.getVertex(i1).texCoord;
 //       const float* w2 = model.getVertex(i2).texCoord;
 //       const float* w3 = model.getVertex(i3).texCoord;
 //       
 //       float x1 = v2[0] - v1[0];
 //       float x2 = v3[0] - v1[0];
 //       float y1 = v2[1] - v1[1];
 //       float y2 = v3[1] - v1[1];
 //       float z1 = v2[2] - v1[2];
 //       float z2 = v3[2] - v1[2];
 //       
 //       float s1 = w2[0] - w1[0];
 //       float s2 = w3[0] - w1[0];
 //       float t1 = w2[1] - w1[1];
 //       float t2 = w3[1] - w1[1];
 //       
 //       float r = 1.0f / (s1 * t2 - s2 * t1);

	//	// we do not interpolate the tangents here for all incident triangles normals
	//	modelBuffer[numberOfTriangles*30 + i*9     ] = (t2 * x1 - t1 * x2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 1 ] = (t2 * y1 - t1 * y2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 2 ] = (t2 * z1 - t1 * z2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 3 ] = (t2 * x1 - t1 * x2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 4 ] = (t2 * y1 - t1 * y2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 5 ] = (t2 * z1 - t1 * z2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 6 ] = (t2 * x1 - t1 * x2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 7 ] = (t2 * y1 - t1 * y2) * r;
	//	modelBuffer[numberOfTriangles*30 + i*9 + 8 ] = (t2 * z1 - t1 * z2) * r;
	//}

	for(int i = 0; i < numberOfVertices; i++)
	{
			//float clusterIndex = model.getVertexCluster( model.getIndexBuffer()[i*3 + j] );
			/*modelBuffer[numberOfTriangles*39 + i*3 + j ] = model.getVertexColor( &model.getVertex( model.getIndexBuffer()[i*3 + j] ) );*/
			modelBuffer[numberOfVertices*4 + i*4 ] = model.getColorBuffer()[ i ].color[ 0 ];
			modelBuffer[numberOfVertices*4 + i*4 + 1 ] = model.getColorBuffer()[ i ].color[ 1 ];
			modelBuffer[numberOfVertices*4 + i*4 + 2 ] = model.getColorBuffer()[ i ].color[ 2 ];
			modelBuffer[numberOfVertices*4 + i*4 + 3 ] = 0.0f;
	}

	glBindBuffer(GL_ARRAY_BUFFER, bufferId);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * numberOfVertices * 8, modelBuffer, GL_STREAM_DRAW);
}

void Scene::draw()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindBuffer(GL_ARRAY_BUFFER, bufferId);
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(float) * numberOfVertices * 4));

	switch( renderingMode )
	{
	case RENDERING_MODE_POINT:
		glPointSize( 8.0 );
		glDrawArrays(GL_POINTS, 0, numberOfVertices * 3 );
		break;

	case RENDERING_MODE_TRIANGLES:
		//glDrawArrays(GL_LINE_STRIP, 0, numberOfTriangles * 3 );
		glDrawArrays(GL_TRIANGLES, 0, numberOfVertices * 3 );
		break;
	}

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
}

void Scene::update( float dt )
{
	model.update( dt );
	generateModelBuffer();
}

//void Scene::moveVertex( int vertexIndex, float dx, float dy )
//{
//	model.moveVertex( vertexIndex, dx, dy );
//}

//void Scene::changeDeformationMode()
//{
//	DeformationMode currMode = model.getDeformationMode();
//
//	switch( currMode )
//	{
//	case DEFORMATION_MODE_LINEAR:
//		model.changeDeformationMode( DEFORMATION_MODE_QUADRATIC );
//		break;
//
//	case DEFORMATION_MODE_QUADRATIC:
//		model.changeDeformationMode( DEFORMATION_MODE_LINEAR );
//		break;
//	}
//}
